package com.krain.corelibrary.helper.imageloader;

import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.SparseArray;
import android.widget.ImageView;

import com.krain.corelibrary.R;
import com.krain.corelibrary.helper.ImageHelper;
import com.krain.corelibrary.helper.imageloader.depend.AsyncDrawable;
import com.krain.corelibrary.helper.imageloader.depend.BitmapWorkerTask;
import com.krain.corelibrary.helper.imageloader.depend.DiskLruCache;
import com.krain.corelibrary.helper.imageloader.depend.ImageMemCache;
import com.krain.corelibrary.helper.imageloader.depend.ImageMemCache.ImageMemCacheEvent;
import com.krain.corelibrary.helper.imageloader.depend.LibAsyncTask;
import com.krain.corelibrary.helper.imageloader.depend.LibBitmapDrawable;
import com.orhanobut.logger.Logger;

import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 图片加载类。<br>
 * 可单独在每个组件中自行使用，或在app全局使用该类的一个对象。（自行根据需要控制）<br>
 * <br>
 * 建议新应用可以将其包装为单例全局使用（一次性根据设备划分memory缓存大小）避免OOM。 <br>
 * 里面自带memory缓存及磁盘缓存。memory缓存大小设置应与所写app有关，请根据业务自行调整<br>
 * 
 * @author jackzhou
 */

public class ImageLoaderOrigin {

    private Context                                                mContext;

    /** 默认图片的一个缓存列表，图片通过resourceId只生成一次 */
    private SparseArray<Bitmap>                                    mCacheOfloadingBitmap = new SparseArray<Bitmap>();
    private static WeakHashMap<BitmapWorkerTask, BitmapWorkerTask> sAllTask              = new WeakHashMap<BitmapWorkerTask, BitmapWorkerTask>();

    private ImageMemCache                                          mImageMemCache;
    /** 单独为loading图时使用的内存cache **/
    private ImageMemCache                                          mImageMemCacheForLoadingBitmap;

    /** 磁盘缓存 */
    private DiskLruCache                                           mDiskCache;

    /** 设置图片显示 是否有FadeIn效果 **/
    private boolean                                                mFadeInBitmap         = false;

    /**
     * 重要：本方法中使用了sdk level5的特性。使用本方法，需要保证你的app中android:minSdkVersion 否则使用将不显示加载图片 百分比方式设置缓存大小
     *
     * @param context
     * @param percent
     *            Sets the memory cache size based on a percentage of the device memory class percent is < 0.05 or > .8. 参见：setMemCacheSizePercent方法
     */
    @TargetApi(5)
    public ImageLoaderOrigin(Context context, float percent) {
        this.mContext = context;
        this.mImageMemCache = new ImageMemCache(context, percent);
        this.mImageMemCacheForLoadingBitmap = new ImageMemCache(context, 0.1f);
        init();
    }

    /**
     * 设置缓存固定值大小
     *
     * @param maxSize
     *            单位：字节
     */
    public ImageLoaderOrigin(Context context, int maxSize) {
        this.mContext = context;
        this.mImageMemCache = new ImageMemCache(maxSize);
        this.mImageMemCacheForLoadingBitmap = new ImageMemCache(context, 0.1f);
        init();
    }

    private void init() {
     //   DevUtil.initialize(mContext.getApplicationContext());

        // 磁盘缓存
        mDiskCache = DiskLruCache.openCache(mContext);
    }

    private static final Executor singleThreadExecutor = Executors.newSingleThreadExecutor(new ThreadFactory() {
                                                           private final AtomicInteger mCount = new AtomicInteger(1);

                                                           public Thread newThread(Runnable r) {
                                                               return new Thread(r, "AsyncTask #"
                                                                       + mCount.getAndIncrement());
                                                           }
                                                       });

    /**
     * 从内存缓存中获取图片
     * 
     * @param filePathOrUrl
     * @return
     */
    public Bitmap loadImageFromMemoryCache(String filePathOrUrl) {
        String memKey = generateMemCacheKey(filePathOrUrl, 0, 0, false);
        return mImageMemCache.get(memKey);
    }

    /**
     * 异步加载图片<br>
     * <br>
     * 注意：<br>
     * 该加载内置磁盘及内存缓存机制。<br>
     * 图片在内存缓存满时，为防止OOM会自动recycle掉（已做处理，recycle后图片会透明，不会报：Trying to use recycled bitmap。为了app业务或美观建议设置ImageView的android:background属性。）<br>
     * <br>
     * 需在每个onResume方法中重新加载次图片（自动recycle掉的图片在低版本rom下会显示透明，高版本rom中部分会正常显示图片， 但部分rom会直接花屏或显示黑色背景图片。）
     * 
     * @param imageView
     *            显示图片的控件
     * @param filePathOrUrl
     *            加载图片的本地路径或网络url
     * @param loadingBitmap
     *            加载图片时loading图
     * @param imageLoaderEvent
     *            用户自定义当图片加载完成时的动作
     */
    public void loadImage(final ImageView imageView, String filePathOrUrl, final Bitmap loadingBitmap,
            ImageLoaderEvent imageLoaderEvent) {
        loadImage(imageView, filePathOrUrl, loadingBitmap, 0, 0, false, imageLoaderEvent);
    }

    /**
     * 异步加载图片<br>
     * <br>
     * 注意：<br>
     * 该加载内置磁盘及内存缓存机制。<br>
     * 图片在内存缓存满时，为防止OOM会自动recycle掉（已做处理，recycle后图片会透明，不会报：Trying to use recycled bitmap。为了app业务或美观建议设置ImageView的android:background属性。）<br>
     * <br>
     * 需在每个onResume方法中重新加载次图片（自动recycle掉的图片在低版本rom下会显示透明，高版本rom中部分会正常显示图片， 但部分rom会直接花屏或显示黑色背景图片。）
     * 
     * @param imageView
     *            显示图片的控件
     * @param filePathOrUrl
     *            加载图片的本地路径或网络url
     * @param loadingBitmap
     *            加载图片时loading图
     */
    public void loadImage(final ImageView imageView, String filePathOrUrl, final Bitmap loadingBitmap) {
        loadImage(imageView, filePathOrUrl, loadingBitmap, 0, 0, false);
    }

    /**
     * 异步加载图片，可以按比例缩放及裁剪图片<br>
     * <br>
     * 重要：本方法中isNeedCut=true使用了sdk level8的特性。使用本方法，需要保证你的app中android:minSdkVersion大于等于8，否则在低版本中会异常 <br>
     * <br>
     * 该加载内置磁盘及内存缓存机制。<br>
     * 图片在内存缓存满时，为防止OOM会自动recycle掉（已做处理，recycle后图片会透明，不会报：Trying to use recycled bitmap。为了app业务或美观建议设置ImageView的android:background属性。）<br>
     * <br>
     * 需在每个onResume方法中重新加载次图片（自动recycle掉的图片在低版本rom下会显示透明，高版本rom中部分会正常显示图片， 但部分rom会直接花屏或显示黑色背景图片。）
     * 
     * @param imageView
     *            显示图片的控件
     * @param filePathOrUrl
     *            加载图片的本地路径或网络url
     * @param loadingBitmap
     *            加载图片时loading图
     * @param width
     *            宽
     * @param height
     *            高
     * @param isNeedCut
     *            缩放时是否需要裁剪 true:缩放后将大于指定width和height的裁剪掉 false:仅按比例缩放保证图片宽和高不大于width和height
     */
    @TargetApi(8)
    public void loadImage(final ImageView imageView, String filePathOrUrl, final Bitmap loadingBitmap, int width,
            int height, boolean isNeedCut) {
        loadImage(imageView, filePathOrUrl, loadingBitmap, width, height, isNeedCut, null);
    }

    /**
     * 异步加载图片，可以按比例缩放及裁剪图片<br>
     * <br>
     * 重要：本方法中isNeedCut=true使用了sdk level8的特性。使用本方法，需要保证你的app中android:minSdkVersion大于等于8，否则在低版本中会异常 <br>
     * <br>
     * 该加载内置磁盘及内存缓存机制。<br>
     * 图片在内存缓存满时，为防止OOM会自动recycle掉（已做处理，recycle后图片会透明，不会报：Trying to use recycled bitmap。为了app业务或美观建议设置ImageView的android:background属性。）<br>
     * <br>
     * 需在每个onResume方法中重新加载次图片（自动recycle掉的图片在低版本rom下会显示透明，高版本rom中部分会正常显示图片， 但部分rom会直接花屏或显示黑色背景图片。）
     * 
     * @param imageView
     *            显示图片的控件
     * @param filePathOrUrl
     *            加载图片的本地路径或网络url
     * @param loadingBitmap
     *            加载图片时loading图
     * @param width
     *            宽
     * @param height
     *            高
     * @param isNeedCut
     *            缩放时是否需要裁剪 true:缩放后将大于指定width和height的裁剪掉 false:仅按比例缩放保证图片宽和高不大于width和height
     * @param imageLoaderEvent
     *            用户自定义当图片加载完成时的动作
     */
    @TargetApi(8)
    public void loadImage(final ImageView imageView, String filePathOrUrl, Bitmap loadingBitmap, int width, int height,
            boolean isNeedCut, ImageLoaderEvent imageLoaderEvent) {
        // 异常处理 为null则使用透明图片
        if (loadingBitmap == null) {
            loadingBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.lib_transparent);
        }
        if (filePathOrUrl == null || filePathOrUrl.trim().length() == 0) {
            imageView.setImageBitmap(loadingBitmap);
            return;
        }

        /*
         * 加载图片逻辑 1.mem缓存命中，直接显示 2.mem缓存未命中，磁盘缓存命中，使用独立线程池，与网络下载的线程池分开，提高加载速度 3.全未命中，第一次加载图片使用自定义的继承LibAsyncTask类，单线程队列下载和加载图片
         */
        // memcache状态
       // DevUtil.v("jackzhou", String.format(
        Logger.v("jackzhou", String.format(
                "mImageMemCache(%s) status: size=%s - maxSize=%s - size*100/maxSize=%s - hitCount=%s - missCount=%s",
                mImageMemCache.hashCode(),
                mImageMemCache.size(), mImageMemCache.maxSize(),
                mImageMemCache.size() * 100 / mImageMemCache.maxSize(), mImageMemCache.hitCount(),
                mImageMemCache.missCount()));
        // mem缓存命中
        String memKey = generateMemCacheKey(filePathOrUrl, width, height, isNeedCut);
        if (isMemCached(memKey)) {
            Bitmap bitmap = mImageMemCache.get(memKey);
            imageView.setImageDrawable(new LibBitmapDrawable(mContext.getResources(), bitmap));
            // 处理用户自定义事件
            if (imageLoaderEvent != null && imageView != null) {
                imageLoaderEvent.onImageFinish(imageView, bitmap);
            }
            return;
        }

        // loadingBitmap纳入内存管理
        mImageMemCacheForLoadingBitmap.put(String.valueOf(loadingBitmap.hashCode()), loadingBitmap);

        // 磁盘缓存命中
        if (isDiskCached(filePathOrUrl, width, height, isNeedCut)) {

            if (BitmapWorkerTask.cancelPotentialWork(filePathOrUrl, imageView)) {

                final BitmapWorkerTask task = new BitmapWorkerTask(filePathOrUrl, imageView, loadingBitmap,
                        mImageMemCache, mDiskCache, width, height, isNeedCut, imageLoaderEvent);
                task.setIsFadeInBitmap(mFadeInBitmap);
                final AsyncDrawable asyncDrawable = new AsyncDrawable(imageView.getResources(), loadingBitmap, task);
                imageView.setImageDrawable(asyncDrawable);

                addToTaskQueue(task);

                task.executeOnExecutor(singleThreadExecutor);
            //    DevUtil.v("jackzhou",
                Logger.v("jackzhou",
                        String.format("mImageMemCache ++++++++++++ Executor:singleThreadExecutor task:%s", task));
            }

            return;
        }

        // 第一次加载
        if (BitmapWorkerTask.cancelPotentialWork(filePathOrUrl, imageView)) {

            final BitmapWorkerTask task = new BitmapWorkerTask(filePathOrUrl, imageView, loadingBitmap, mImageMemCache,
                    mDiskCache, width, height, isNeedCut, imageLoaderEvent);
            task.setIsFadeInBitmap(mFadeInBitmap);
            final AsyncDrawable asyncDrawable = new AsyncDrawable(imageView.getResources(), loadingBitmap, task);
            imageView.setImageDrawable(asyncDrawable);

            addToTaskQueue(task);

            task.executeOnExecutor(LibAsyncTask.SERIAL_EXECUTOR);// 这里一次只会有一个tast执行
                                                                 // BitmapWorkerTask继承新的AsyncTask。
            //DevUtil.v("jackzhou",
                    Logger.v("jackzhou",
                    String.format("mImageMemCache ------------ Executor:LibAsyncTask.SERIAL_EXECUTOR task:%s", task));
        }

    }

    /**
     * 异步加载图片<br>
     * <br>
     * 注意：<br>
     * 该加载内置磁盘及内存缓存机制。<br>
     * 图片在内存缓存满时，为防止OOM会自动recycle掉（已做处理，recycle后图片会透明，不会报：Trying to use recycled bitmap。为了app业务或美观建议设置ImageView的android:background属性。）<br>
     * <br>
     * 需在每个onResume方法中重新加载次图片（自动recycle掉的图片在低版本rom下会显示透明，高版本rom中部分会正常显示图片， 但部分rom会直接花屏或显示黑色背景图片。）
     * 
     * @param imageView
     *            显示图片的控件
     * @param filePathOrUrl
     *            加载图片的本地路径或网络url
     * @param loadingBitmapResId
     *            加载图片时loading图资源id
     * @param imageLoaderEvent
     *            用户自定义当图片加载完成时的动作
     */
    public void loadImage(final ImageView imageView, String filePathOrUrl, int loadingBitmapResId,
            ImageLoaderEvent imageLoaderEvent) {
        loadImage(imageView, filePathOrUrl, loadingBitmapResId, 0, 0, false, imageLoaderEvent);
    }

    /**
     * 异步加载图片<br>
     * <br>
     * 注意：<br>
     * 该加载内置磁盘及内存缓存机制。<br>
     * 图片在内存缓存满时，为防止OOM会自动recycle掉（已做处理，recycle后图片会透明，不会报：Trying to use recycled bitmap。为了app业务或美观建议设置ImageView的android:background属性。）<br>
     * <br>
     * 需在每个onResume方法中重新加载次图片（自动recycle掉的图片在低版本rom下会显示透明，高版本rom中部分会正常显示图片， 但部分rom会直接花屏或显示黑色背景图片。）
     * 
     * @param imageView
     *            显示图片的控件
     * @param filePathOrUrl
     *            加载图片的本地路径或网络url
     * @param loadingBitmapResId
     *            加载图片时loading图资源id
     */
    public void loadImage(final ImageView imageView, String filePathOrUrl, int loadingBitmapResId) {
        loadImage(imageView, filePathOrUrl, loadingBitmapResId, 0, 0, false);
    }

    /**
     * 异步加载图片，可以按比例缩放图片 缩放保证图片宽和高不大于width和height<br>
     * <br>
     * 该加载内置磁盘及内存缓存机制。<br>
     * 图片在内存缓存满时，为防止OOM会自动recycle掉（已做处理，recycle后图片会透明，不会报：Trying to use recycled bitmap。为了app业务或美观建议设置ImageView的android:background属性。）<br>
     * <br>
     * 需在每个onResume方法中重新加载次图片（自动recycle掉的图片在低版本rom下会显示透明，高版本rom中部分会正常显示图片， 但部分rom会直接花屏或显示黑色背景图片。）
     * 
     * @param imageView
     *            显示图片的控件
     * @param filePathOrUrl
     *            加载图片的本地路径或网络url
     * @param loadingBitmapResId
     *            加载图片时loading图资源id
     * @param width
     *            宽
     * @param height
     *            高
     */
    public void loadImage(final ImageView imageView, String filePathOrUrl, int loadingBitmapResId, int width, int height) {
        loadImage(imageView, filePathOrUrl, loadingBitmapResId, width, height, false);
    }

    /**
     * 异步加载图片，可以按比例缩放及裁剪图片<br>
     * <br>
     * 重要：本方法中isNeedCut=true使用了sdk level8的特性。使用本方法，需要保证你的app中android:minSdkVersion大于等于8，否则在低版本中会异常 <br>
     * <br>
     * 该加载内置磁盘及内存缓存机制。<br>
     * 图片在内存缓存满时，为防止OOM会自动recycle掉（已做处理，recycle后图片会透明，不会报：Trying to use recycled bitmap。为了app业务或美观建议设置ImageView的android:background属性。）<br>
     * <br>
     * 需在每个onResume方法中重新加载次图片（自动recycle掉的图片在低版本rom下会显示透明，高版本rom中部分会正常显示图片， 但部分rom会直接花屏或显示黑色背景图片。）
     * 
     * @param imageView
     *            显示图片的控件
     * @param filePathOrUrl
     *            加载图片的本地路径或网络url
     * @param loadingBitmapResId
     *            加载图片时loading图
     * @param width
     *            宽
     * @param height
     *            高
     * @param isNeedCut
     *            缩放时是否需要裁剪 true:缩放后将大于指定width和height的裁剪掉 false:仅按比例缩放保证图片宽和高不大于width和height
     * @param imageLoaderEvent
     *            用户自定义当图片加载完成时的动作
     */
    @TargetApi(8)
    public void loadImage(ImageView imageView, String filePathOrUrl, int loadingBitmapResId, int width, int height,
            boolean isNeedCut, ImageLoaderEvent imageLoaderEvent) {

        if (loadingBitmapResId == -1) {
            loadingBitmapResId = R.drawable.lib_transparent;
        }

        // 加载时显示的默认图
        Bitmap loadingBitmap = mCacheOfloadingBitmap.get(loadingBitmapResId);
        if (loadingBitmap == null) {
            loadingBitmap = BitmapFactory.decodeResource(imageView.getResources(), loadingBitmapResId);
            mCacheOfloadingBitmap.put(loadingBitmapResId, loadingBitmap);
        }

        loadImage(imageView, filePathOrUrl, loadingBitmap, width, height, isNeedCut, imageLoaderEvent);
    }

    /**
     * 异步加载图片，可以按比例缩放及裁剪图片<br>
     * <br>
     * 重要：本方法中isNeedCut=true使用了sdk level8的特性。使用本方法，需要保证你的app中android:minSdkVersion大于等于8，否则在低版本中会异常 <br>
     * <br>
     * 该加载内置磁盘及内存缓存机制。<br>
     * 图片在内存缓存满时，为防止OOM会自动recycle掉（已做处理，recycle后图片会透明，不会报：Trying to use recycled bitmap。为了app业务或美观建议设置ImageView的android:background属性。）<br>
     * <br>
     * 需在每个onResume方法中重新加载次图片（自动recycle掉的图片在低版本rom下会显示透明，高版本rom中部分会正常显示图片， 但部分rom会直接花屏或显示黑色背景图片。）
     * 
     * @param imageView
     *            显示图片的控件
     * @param filePathOrUrl
     *            加载图片的本地路径或网络url
     * @param loadingBitmapResId
     *            加载图片时loading图
     * @param width
     *            宽
     * @param height
     *            高
     * @param isNeedCut
     *            缩放时是否需要裁剪 true:缩放后将大于指定width和height的裁剪掉 false:仅按比例缩放保证图片宽和高不大于width和height
     */
    @TargetApi(8)
    public void loadImage(ImageView imageView, String filePathOrUrl, int loadingBitmapResId, int width, int height,
            boolean isNeedCut) {
        if (loadingBitmapResId == -1) {
            loadingBitmapResId = R.drawable.lib_transparent;
        }

        // 加载时显示的默认图
        Bitmap loadingBitmap = mCacheOfloadingBitmap.get(loadingBitmapResId);
        if (loadingBitmap == null) {
            loadingBitmap = BitmapFactory.decodeResource(imageView.getResources(), loadingBitmapResId);
            mCacheOfloadingBitmap.put(loadingBitmapResId, loadingBitmap);
        }

        loadImage(imageView, filePathOrUrl, loadingBitmap, width, height, isNeedCut);
    }

    /**
     * 清空Memory缓存，所有图片会被recycle. 已作处理，可放心使用，recycle的图片不会报：trying to use a recycled bitmap错误<br>
     * 建议在onPause及onDestroy中调用该方法
     */
    public void clearMemoryCache() {
        mImageMemCache.clearCache();
        mImageMemCacheForLoadingBitmap.clearCache();
    }

    /**
     * 移除单个Memory缓存，图片会被recycle. 已作处理，可放心使用，recycle的图片不会报：trying to use a recycled bitmap错误<br>
     * 
     * @param key
     * @return
     */
    public Bitmap removeMemoryCache(String key) {
        return mImageMemCache.remove(key);
    }

    /**
     * 得到Memory缓存内容
     * 
     * @return
     */
    public Map<String, Bitmap> snapshot() {
        return mImageMemCache.snapshot();
    }

    /**
     * 设置memory缓存大小 单位：字节
     * 
     * @param maxSize
     */
    public void setMemCacheSize(int maxSize) {
        mImageMemCache.setCacheSize(maxSize);
    }

    /**
     * 得到缓存大小 单位：字节
     * 
     * @return
     */
    public int getMemCacheSize() {
        return mImageMemCache.getMemCacheSize();
    }

    /**
     * 设置loading默认图的memory缓存大小
     * 
     * @param maxSize
     */
    public void setMemCacheSizeOfLoadingBitmap(int maxSize) {
        mImageMemCacheForLoadingBitmap.setCacheSize(maxSize);
    }

    /**
     * 是否在内存中缓存
     * 
     * @return
     */
    public boolean isMemCached(String memKey) {

        Bitmap temp = mImageMemCache.get(memKey);

        if (temp == null) {
            return false;
        } else {
            //DevUtil.v("jackzhou", String.format("mImageMemCache(%s) memcache hit. memKey = '%s'", mImageMemCache.hashCode(),
            Logger.v("jackzhou", String.format("mImageMemCache(%s) memcache hit. memKey = '%s'", mImageMemCache.hashCode(),
                    memKey));
            return true;
        }
    }

    /**
     * 是否磁盘缓存
     * 
     * @param filePathOrUrl
     * @param width
     * @param height
     * @return
     */
    private boolean isDiskCached(String filePathOrUrl, int width, int height, boolean isNeedCut) {
    	if(mDiskCache == null){
    		return false;
    	}else{
    		return mDiskCache.containsKey(ImageHelper.generateDiskCacheKey(filePathOrUrl, width, height, isNeedCut));
    	}
    }

    /**
     * 生成memory缓存的key
     * 
     * @param filePathOrUrl
     * @param width
     * @param height
     * @param isNeedCut
     * @return
     */
    public static String generateMemCacheKey(String filePathOrUrl, int width, int height, boolean isNeedCut) {
        return String.format("%s%s%s%s", String.valueOf(filePathOrUrl), width, height, isNeedCut);
    }

    /**
     * 
     * @param filePathOrUrl
     * @param width
     * @param height
     * @param isNeedCut
     * @return
     */
    public static String generateDiskCacheKey(String filePathOrUrl, int width, int height, boolean isNeedCut) {
        return ImageHelper.generateDiskCacheKey(filePathOrUrl, width, height, isNeedCut);
    }

    /**
     * 对外提供用于处理缓存回收时的自定义动作。不设置则默认：将图片recycle
     * 
     * @param imageMemCacheEvent
     */
    public void setImageMemCacheEvent(ImageMemCacheEvent imageMemCacheEvent) {
        mImageMemCache.setImageMemCacheEvent(imageMemCacheEvent);
    }

    /**
     * 设置图片显示 是否有FadeIn效果
     * 
     * @param isFadeInBitmap
     */
    public void setIsFadeInBitmap(boolean isFadeInBitmap) {
        mFadeInBitmap = isFadeInBitmap;
    }

    /**
     * 该接口提供自定义事件，供用户处理。
     */
    public interface ImageLoaderEvent {
        /**
         * 该方法定义当图片下载完成时（或本地图片load完时）的动作 <br>
         * <br>
         * 注意：方法在主线程中运行，不要放入耗时操作
         * 
         * @param imageView
         * @param bitmap
         *            加载完成时的图片,地址错误时无法加载则为null
         */
        public void onImageFinish(ImageView imageView, Bitmap bitmap);

    }

    /**
     * 图片加载失败或错误时，显示errorResId图片
     * 
     * @param imageView
     * @param filePathOrUrl
     * @param width
     * @param height
     * @param resId
     * @param errorResId
     */
    public void loadImage(ImageView imageView, String filePathOrUrl, int width, int height, int resId,
            final int errorResId) {

        loadImage(imageView, filePathOrUrl, resId, width, height, true, new ImageLoaderEvent() {

            @Override
            public void onImageFinish(ImageView imageView, Bitmap bitmap) {
                if (bitmap == null) {
                    imageView.setImageResource(errorResId);
                }
            }
        });
    }

    /**
     * 取消任务
     */
    public void cancleTask() {
        if (sAllTask == null || sAllTask.size() == 0) {
            return;
        }

        for (BitmapWorkerTask temp : sAllTask.keySet()) {
            if (temp != null && !temp.isCancelled()) {
                temp.cancel(true);
            }

        }

        synchronized (sAllTask) {
            sAllTask.clear();
        }
    }

    private void addToTaskQueue(BitmapWorkerTask task) {
        synchronized (sAllTask) {
            sAllTask.put(task, task);
        }
    }

    /**
     * 获取任务队列
     * 
     * @return
     */
    public static WeakHashMap<BitmapWorkerTask, BitmapWorkerTask> getMTaskQueue() {
        return sAllTask;
    }
}
